fix: support formatter functions in ECharts code blocks#6767
fix: support formatter functions in ECharts code blocks#6767octo-patch wants to merge 1 commit intolabring:mainfrom
Conversation
…g#6536) When an ECharts config contains formatter or other function values, json5.parse() fails silently and the chart renders as a blank box. Add a fallback that evaluates the config as a JavaScript expression using the Function constructor, enabling formatter callbacks to work. json5.parse() is still attempted first as it is safer for standard JSON5 configs.
|
octo-patch seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account. You have signed the CLA already but the status is still pending? Let us recheck it. |
1 similar comment
|
octo-patch seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account. You have signed the CLA already but the status is still pending? Let us recheck it. |
|
✅ Build Successful - Preview code-sandbox Image for this PR: |
|
✅ Build Successful - Preview fastgpt Image for this PR: |
|
✅ Build Successful - Preview mcp_server Image for this PR: |
|
Please confirm whether there is a risk of injection attacks in this approach. |
|
@c121914yu Yes — The practical risk depends on the trust model for ECharts code-block content:
If you'd prefer a safer fix, I can switch to one of:
Happy to update the PR to whichever direction you prefer, or close it if you'd rather not widen the surface at all. My preference would be option 1 (AST guard) — it covers most formatter callbacks people write while keeping the dangerous eval features off-limits. Let me know which way you'd like to go. |
c121914yu
left a comment
There was a problem hiding this comment.
前端安全 Review
这个改动不能直接合并。PR 解决的 formatter 空白问题是真实存在的,但当前实现把 Markdown 代码块内容作为 JavaScript 表达式在浏览器里执行,会把普通 Markdown 渲染链路变成任意 JS 执行入口。
阻塞点在 projects/app/src/components/Markdown/img/EChartsCodeBlock.tsx 的新增逻辑:
const userOption = new Function(`return (${code.trim()})`)();code 来自 echarts Markdown code block,不是可信管理员配置。FastGPT 的 Markdown 组件会渲染聊天回复、引用、通知、插件说明、数据预览等内容;isDisabled 也只是遮罩,不会阻止子组件执行。因此攻击者只要让页面渲染一段 echarts Markdown,就可以在当前登录用户上下文执行任意脚本、读取前端可访问数据并调用同源 API。
建议不要采用 new Function / eval,也不建议做“AST guard 后执行 JS function”。AST guard 很容易在后续 ECharts formatter 复杂化时变成长期绕过面,而且仍然需要维护一套 JavaScript sandbox 语义。
更合适的修复方向:继续只用 JSON/JSON5 解析用户配置,然后提供安全的 formatter preset / DSL。例如支持:
{
tooltip: {
trigger: 'axis',
axisPointer: { type: 'shadow' },
formatterPreset: 'axisSeriesList'
}
}组件内部把 preset 映射到固定函数:
const formatterPresets = {
axisSeriesList: (params: any) => {
const list = Array.isArray(params) ? params : [params];
const title = escapeHtml(String(list[0]?.name ?? ''));
return [
`${title}<br/>`,
...list.map((item) => {
const marker = item.marker ?? '';
const name = escapeHtml(String(item.seriesName ?? ''));
const value = escapeHtml(String(item.value ?? ''));
return `${marker}${name}: ${value}<br/>`;
})
].join('');
}
};这能覆盖 issue #6536 里的多 series tooltip 展示需求,同时不会执行用户提交的 JS。后续如有更多场景,可以扩展 singleSeries、nameValue、percentPie、valueWithUnit 等 preset,或者提供非常有限的字符串模板 DSL,但不要执行函数体。
Fixes #6536
Problem
When an ECharts configuration contains
formatter(or other function-valued properties),json5.parse()throws aSyntaxErrorbecause function literals are not valid JSON5. The error is silently caught,optionbecomesundefined, andsetOption({})is called — the chart renders as a blank white box with no error shown.Solution
Add a fallback parser that evaluates the ECharts config as a JavaScript expression using the
Functionconstructor. This allows formatter callbacks and other JS function values to work correctly.json5.parse()is still tried first (safer, handles comments/trailing commas)Functionconstructor fallback is usedbuildOptionhelper is extracted to avoid duplication between the two pathsTesting
Using an ECharts code block with a
formatterfunction (as in the issue report) now renders the chart correctly instead of showing a blank box.